package com.yonyou.le.unattended.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.google.gson.Gson;
import com.yonyou.le.unattended.cache.DeviceCacheManager;
import com.yonyou.le.unattended.cache.entity.DeviceData;
import com.yonyou.le.unattended.cache.entity.OPCache;
import com.yonyou.le.unattended.delivery.entity.AdaptorParamVO;
import com.yonyou.le.unattended.delivery.entity.DeliveryParamVO;
import com.yonyou.le.unattended.delivery.entity.DevGroupParamVO;
import com.yonyou.le.unattended.delivery.entity.DeviceParamVO;
import com.yonyou.le.unattended.delivery.entity.EWDocParamVO;
import com.yonyou.le.unattended.delivery.entity.OperatPointParamVO;
import com.yonyou.le.unattended.entity.meta.OperationPoint;
import com.yonyou.le.unattended.util.CalServletForLE;
import com.yonyou.le.unattended.util.CommonUtils;
import com.yonyou.le.unattended.util.FindDevice;
import com.yonyou.tool.servlet.NCConnService;

/**
 * 初始化缓存信息的服务
 * 设备信息、设备分类、适配器、作业点和动作信息
 * @author zhangbbd
 *
 */
@Component
public class DeviceDataService {
	private Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private DeviceCacheManager cacheManager; 
	
	private final String hcdevcode="hcdevcode";
	private final String pk_devicegroup="pk_devicegroup";
	private final String bcdeviceid="bcdeviceid";
	private final String bcmeanewid="bcmeanewid";
	private final String pk_device="pk_device";
	private final String pk_ew="pk_ew";
	private final String hcopercode="hcopercode";
	
	
	
	@Value("${le.ip}")  
	public String ip;
	@Value("${le.port}")  
	public int port;

	/**
	 * 查询设备信息、设备分类、适配器、作业点和动作信息，并存入缓存
	 */
	public void initializeDeviceData(){
		logger.debug("初始化设备信息");
		
		NCConnService client = new NCConnService(ip,port);
		//查询返回jsonarray
		String jsonString = (String) client.callNCService(CalServletForLE.getDeliveryQueryContext(), null, null);
		if(jsonString == null){
			logger.error("Could not access data from le , please makesure LE is running!");
		}
		//System.out.println(jsonString);
		Gson gs = new Gson();
		DeliveryParamVO data = gs.fromJson(jsonString, DeliveryParamVO.class);
		//logger.debug(jsonString);
		
		//信息建立索引
		Map<String,DeviceParamVO> deviceMap = CommonUtils.list2Map(data.getDeviceParamList(), hcdevcode);
		Map<String,EWDocParamVO> ewMap_pk = CommonUtils.list2Map(data.getEwDocParamList(), pk_ew);
		Map<String,DevGroupParamVO> devGroupMap = CommonUtils.list2Map(data.getDevGroupParamList(),pk_devicegroup);
		Map<String, AdaptorParamVO> adaptorMap = CommonUtils.list2Map(data.getAdaptorParamList(),bcdeviceid);		
		Map<String, List<OperatPointParamVO>> operaPointMap = CommonUtils.list2Maplist(data.getOperaPointParamList(),bcdeviceid);
		
		//数据处理 数据缓存
		//衡器信息
		Map<String, AdaptorParamVO> adaptorMap_mean = CommonUtils.list2Map(data.getAdaptorParamList(),bcmeanewid);		
		Map<String, List<OperatPointParamVO>> operaPointMap_mean = CommonUtils.list2Maplist(data.getOperaPointParamList(),bcmeanewid);
		
		//缓存设备
		initDevcieCache(deviceMap, devGroupMap, adaptorMap, operaPointMap);
		
		//缓存衡器
		initMeanewCache(ewMap_pk,adaptorMap_mean,operaPointMap_mean);
		
		
		//根据作业点编码来找杆(设备)的缓存
		Map<String,DeviceParamVO> deviceMap_pk = CommonUtils.list2Map(data.getDeviceParamList(), pk_device);//按照device pk来分别
		Map<String, List<OperatPointParamVO>> operaPointMap2 = CommonUtils.list2Maplist(data.getOperaPointParamList(),hcopercode);
		initMOperateToDevice(operaPointMap2,devGroupMap, deviceMap_pk,ewMap_pk);
		//初始化作业点列表
		initOPCache(operaPointMap2);
	}
	/**
	 * 缓存设备信息、分类、适配器、作业点,存储为<deviceCode,deviceData>
	 * @param deviceMap
	 * @param devGroupMap
	 * @param adaptorMap
	 * @param operaPointMap
	 */
	private void initDevcieCache(Map<String, DeviceParamVO> deviceMap, Map<String, DevGroupParamVO> devGroupMap, Map<String, AdaptorParamVO> adaptorMap, Map<String, List<OperatPointParamVO>> operaPointMap){
		for (DeviceParamVO device : deviceMap.values()) {
			//找到设备对应的类型、适配器、作业点
			String devGroupCode=device.getHcdevgroup();
			DevGroupParamVO devGroupParamVO = devGroupMap.get(devGroupCode);
			AdaptorParamVO adaptorParamVO = adaptorMap.get(device.getPk_device());
			List<OperatPointParamVO> operatPointParamVOs = operaPointMap.get(device.getPk_device());
			DeviceData deviceData = new DeviceData(device, devGroupParamVO, adaptorParamVO, operatPointParamVOs);
			//存入缓存
			cacheManager.updateDeviceData(device.getHcdevcode(),deviceData);
		}
	}
	/**
	 * 缓存衡器、适配器、作业点，存储为<deviceCode,deviceData>
	 * @param adaptorMap_mean
	 * @param operaPointMap_mean
	 */
	private void initMeanewCache(Map<String,EWDocParamVO> ewMap,Map<String, AdaptorParamVO> adaptorMap_mean, Map<String, List<OperatPointParamVO>> operaPointMap_mean){
		for (EWDocParamVO ewDocParamVO : ewMap.values()) {
			String ewPK = ewDocParamVO.getPk_ew();
			AdaptorParamVO adaptor = adaptorMap_mean.get(ewPK);
			List<OperatPointParamVO> list = operaPointMap_mean.get(ewPK);
			DeviceData deviceData = new DeviceData(ewDocParamVO, adaptor, list);
			cacheManager.updateDeviceData(ewDocParamVO.getVcode(),deviceData);
		}
	}
	
	/**
	 *  按照  <作业点，设备位置-设备类型，设备编码>的格式来缓存
	 *  enumeration 2:LED,  3:道闸，8:红外  1:摄像头
	 * @param operaPointMap
	 * @param devGroupMap
	 * @param deviceMap2
	 * @param ewMap
	 */
	private void initMOperateToDevice(Map<String, List<OperatPointParamVO>> operaPointMap,Map<String, DevGroupParamVO> devGroupMap, Map<String, DeviceParamVO> deviceMap_pk, Map<String, EWDocParamVO> ewMap){
		for (Entry<String, List<OperatPointParamVO>> entry: operaPointMap.entrySet()) {
			Map<String,String> op_deviceCodeMap = new HashMap<String, String>();//位置-类型，设备
			
			List<OperatPointParamVO> devices = entry.getValue();
			String opcode = null;
			for (int i = 0; i < devices.size(); i++) {
				OperatPointParamVO operatPointParamVO = devices.get(i);
				//作业点下的opcode都一样，只取一次
				if(opcode == null)
					opcode = operatPointParamVO.getHcopercode();
				
				if(operatPointParamVO.getBcdeviceid()!=null){
					DeviceParamVO deviceVO=deviceMap_pk.get(operatPointParamVO.getBcdeviceid());
					DevGroupParamVO devGroupParamVO = devGroupMap.get(deviceVO.getHcdevgroup());
					Integer hfdevtype = devGroupParamVO.getHfdevtype();//设备类型
					String position =operatPointParamVO.getBcdeviceposition();//设备位置
					if(hfdevtype!=null){
						if(StringUtils.isNotBlank(position))
							op_deviceCodeMap.put(position+"-"+hfdevtype, deviceVO.getHcdevcode());
						else{//没有设备位置的设备，存储时存储为列表
							String postype = FindDevice.getNonepositionType(hfdevtype);
							String codeArray = null ;
							if(op_deviceCodeMap.containsKey(postype)){
								codeArray=op_deviceCodeMap.get(postype);
							}
							if(StringUtils.isNotBlank(codeArray))
								op_deviceCodeMap.put(postype, codeArray + "-"+ deviceVO.getHcdevcode());
							else
								op_deviceCodeMap.put(postype, deviceVO.getHcdevcode());
						}
							
					}						
					else{
						logger.error("THE deviceType is blank or null opcode="+opcode +
								" and deviceid="+ operatPointParamVO.getBcdeviceid());
					}
				}else if(operatPointParamVO.getBcmeanewid()!=null){
					EWDocParamVO ewDocParamVO = ewMap.get(operatPointParamVO.getBcmeanewid());					
					op_deviceCodeMap.put(FindDevice.getWeightPositionAndType(), ewDocParamVO.getVcode());//衡器的类型
				}
			}
			
			cacheManager.updateMonitorData(opcode, op_deviceCodeMap);
		}
		
	}
	/**
	 * 初始化作业点列表
	 * @param operaPointMap
	 */
	private void initOPCache(Map<String, List<OperatPointParamVO>> operaPointMap){
		Iterator<Entry<String, List<OperatPointParamVO>>> iterator = operaPointMap.entrySet().iterator();		
		List<OperationPoint> list=new ArrayList<OperationPoint>();
		while (iterator.hasNext()) {
			Entry<String, List<OperatPointParamVO>> ent = (Entry<String, List<OperatPointParamVO>>) iterator.next();
			List<OperatPointParamVO> ops = ent.getValue();
			if(ops!=null&&ops.size()>0){
				OperatPointParamVO operatPointParamVO = ops.get(0);
				OperationPoint op=new OperationPoint();
				op.setId(operatPointParamVO.getPk_operpoint());
				op.setOpcode(operatPointParamVO.getHcopercode());
				op.setOpname(operatPointParamVO.getHcopername());
				list.add(op);
			}
		}
		OPCache opcache=new OPCache(list);
		cacheManager.setOPList(DeviceCacheManager.LIST_OP, opcache);
					
	}
	
}